from redis import StrictRedis as Redis
from msgpack import dumps, loads
from functools import wraps
import inspect
from wt.db.redis.key_maker import key_maker
from wt.db.redis.config import REDIS


class Cache(Redis):
    def __call__(self, key=None, expire=None, cast=str):
        if key is not None:
            if inspect.isfunction(key):
                return self()(key)
            if isinstance(key, int):
                return self(expire=key)

        def _(func):
            _key = key_maker(key, func)

            @wraps(func)
            def __(*args, **kwds):
                k = _key(*args, **kwds)
                r = self.get(k)
                if r:
                    r = loads(r)
                    if type(r) is bytes:
                        r = r.decode('utf-8', 'ignore')
                else:
                    r = func(*args, **kwds)
                    self.set(k, dumps(r), ex=expire)
                return r

            def rm(*args, **kwds):
                k = _key(*args, **kwds)
                self.delete(k)

            __.rm = rm
            return __

        return _


cache = Cache(**REDIS.CACHE)

if __name__ == "__main__":

    class A:
        def __init__(self):
            self.id = 99

        @cache(60)
        def test(self, a, b):
            print(("run test", a, b))
            return a + b

        @cache
        def test2(self, a, b):
            print(("run test2", a, b))
            return a + b

        @cache("{self.id}", 5)
        def test3(self, a, b):
            print(("run test3", a, b))
            return a + b

    # print((REDIS.CACHE))

    def main():
        cache.flushdb()
        a = A()
        print((a.test(2, 1)))
        print((a.test(2, 1)))
        A.test.rm(a=2, b=1)
        print((a.test(2, 1)))

    cache.flushdb()
    # main()
